package com.liuceng.zen.web.auth.realm;

import com.liuceng.zen.common.utils.Encodes;
import com.liuceng.zen.pojo.domain.Member;
import com.liuceng.zen.service.AccountService;
import com.liuceng.zen.service.MemberService;
import com.liuceng.zen.web.auth.UsernamePasswordToken;
import com.liuceng.zen.web.auth.WechatLoginMatcher;
import com.liuceng.zen.web.auth.realm.ShiroDbRealm.UserContext;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.PostConstruct;

public class WechatLoginDbRealm extends AuthorizingRealm {
  private final static Logger LOG = LoggerFactory.getLogger(WechatLoginDbRealm.class);

  @Value("${wechatlogin.refer}")
  private String refer;
  private AccountService accountService;
  @Autowired
  private MemberService memberSerivce;

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    UserContext userContext = (UserContext) getAvailablePrincipal(principals);
    Member user = accountService.getMemberByUsername(userContext.getUsername());
    if (user != null) {
      SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
      return authorizationInfo;
    }
    return null;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
      throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
    if (!token.getIsWeChatLogin()) {
      return null;
    }
    Member member = memberSerivce.selectByuserName(token.getUsername());
    if (member != null) {
      // 缓存网站配置信息
      byte[] salt = Encodes.decodeHex(member.getSalt());
      return new SimpleAuthenticationInfo(new UserContext(member, false), member.getPassword(),
          ByteSource.Util.bytes(salt), getName());
    } else {
      return null;
    }
  }

  /**
   * 设定Password校验的Hash算法与迭代次数.
   */
  @PostConstruct
  public void initCredentialsMatcher() {
    WechatLoginMatcher matcher = new WechatLoginMatcher(refer);
    setCredentialsMatcher(matcher);
  }

  /**
   * 清空用户关联权限认证，待下次使用时重新加载
   */
  public void clearCachedAuthorizationInfo(String principal) {
    SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
    clearCachedAuthorizationInfo(principals);
  }

  /**
   * 清空所有关联认证
   */
  public void clearAllCachedAuthorizationInfo() {
    Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
    if (cache != null) {
      for (Object key : cache.keys()) {
        cache.remove(key);
      }
    }
  }
}
